﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SMS.Common.Search;
using SMS.Core.DataEntity;
using SMS.Core.DataAccess;
using SMS.Contract;
using SMS.Core;
using System.IO.Ports;
using System.Threading;
using SMS.Service.Properties;

namespace SMS.Service
{
    public class CommSMSService : ISMSService
    {
        #region ISMSService 成员

        #region SMSHandler

        public bool Start(out string message)
        {
            return CommHandler.Start(out message);
        }

        public bool Stop(out string message)
        {
            return CommHandler.Stop(out message);
        }

        public bool SendCommand(string command, out string message)
        {
            try
            {
                var exType = ExceptionType.Unknow;
                var overTime = 10000;
                var totalTime = 0;
                var sleepTime = 100;

                while (CommHandler.ImmediateState)
                {
                    Thread.Sleep(sleepTime);
                    totalTime += sleepTime;
                    if (totalTime >= overTime)
                    {
                        message = Resources.Timeout_Exception;
                        return false;
                    }
                }
                CommHandler.ImmediateState = true;

                totalTime = 0;
                while (!CommHandler.SendState)
                {
                    Thread.Sleep(sleepTime);
                    totalTime += sleepTime;
                    if (totalTime >= overTime)
                    {
                        message = Resources.Timeout_Exception;
                        return false;
                    }
                }
                return CommHandler.SendCommand(command, out message, out exType);
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return false;
            }
            finally
            {
                CommHandler.ImmediateState = false;
            }
        }

        public bool SendMessageImmediately(string number, string content, out string message)
        {
            try
            {
                var exType = ExceptionType.Unknow;
                var overTime = 15000;
                var totalTime = 0;
                var sleepTime = 100;

                while (CommHandler.ImmediateState)
                {
                    Thread.Sleep(sleepTime);
                    totalTime += sleepTime;
                    if (totalTime >= overTime)
                    {
                        message = Resources.Timeout_Exception;
                        return false;
                    }
                }
                CommHandler.ImmediateState = true;

                totalTime = 0;
                while (!CommHandler.SendState)
                {
                    Thread.Sleep(sleepTime);
                    totalTime += sleepTime;
                    if (totalTime >= overTime)
                    {
                        message = Resources.Timeout_Exception;
                        return false;
                    }
                }
                var retries = 0;
                return CommHandler.SendSMS(number, content, out retries, out message, out exType);
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return false;
            }
            finally
            {
                CommHandler.ImmediateState = false;
            }
        }

        public bool SendMessage(string number, string content)
        {
            return SendMessageWithTag(null, number, content);
        }

        public bool SendMessageWithTag(string tag, string number, string content)
        {
            var sendMsg = new SendMessage()
            {
                SendKeyid = Guid.NewGuid().ToString(),
                SystemTag = null,
                EventTag = null,
                SendNumber = GetCurrentNumber(),
                ReceiveNumber = number,
                SendContent = content,
                SendLength = content.Length,
                SendType = (int)SendType.Sequential,
                Priority = 0,
                Retries = 0,
                NeedReply = false,
                ReplyCode = null,
                Status = (int)Status.Waitting,
                ExpireTime = DateTime.Now.AddMinutes(CommConfig.ExpireMimutes),
                HandleTime = null,
                HandleResult = null,
                Sender = null,
                SendTag = tag,
                AddTime = DateTime.Now,
                OrderIndex = 0,
            };
            return AddSendMessage(sendMsg) > 0;
        }

        public string GetCurrentNumber()
        {
            return CommHandler.SendNumber;
        }

        public void SetCurrentNumber(string number)
        {
            CommHandler.SendNumber = number;
        }

        public bool GetConnectionState()
        {
            return CommHandler.ConnectionState;
        }

        public bool GetAutoSendState()
        {
            return CommHandler.AutoSendState;
        }

        public void SetAutoSendState(bool autoSendState)
        {
            CommHandler.AutoSendState = autoSendState;
        }

        public bool GetAutoReceiveState()
        {
            return CommHandler.AutoReceiveState;
        }

        public void SetAutoReceiveState(bool autoReceiveState)
        {
            CommHandler.AutoReceiveState = autoReceiveState;
        }

        #endregion

        #region SendMessage

        public SendMessage GetSendMessage(string sendKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetSingleEntity<SendMessage>(d => d.SendKeyid == sendKeyid);
            }
        }

        public SendMessage[] GetEventTagSendMessage(string eventTag)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<SendMessage>(d => d.EventTag == eventTag).ToArray();
            }
        }

        public int GetStatusWithTag(string tag)
        {
            using (var dc = new SMSAccess())
            {
                var sendMsg = dc.GetFirstEntity<SendMessage>(d => d.SendTag == tag);
                if (sendMsg == null) return -1;
                return sendMsg.Status.GetValueOrDefault();
            }
        }

        public SendMessage[] GetSendMessageWithTag(string tag)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<SendMessage>(d => d.SendTag == tag).ToArray();
            }
        }

        public int GetStatusWithEventTag(string eventTag)
        {
            using (var dc = new SMSAccess())
            {
                var sendMsg = dc.GetFirstEntity<SendMessage>(d => d.EventTag == eventTag);
                if (sendMsg == null) return -1;
                return sendMsg.Status.GetValueOrDefault();
            }
        }

        public SendMessage[] GetSendMessageWithEventTag(string eventTag)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<SendMessage>(d => d.EventTag == eventTag).ToArray();
            }
        }

        public SearchResult<SendMessage> SearchSendMessage(SearchCondition condition)
        {
            using (var dc = new SMSAccess())
            {
                return dc.Search<SendMessage>(condition);
            }
        }

        public int AddSendMessage(SendMessage sendMessage)
        {
            if (sendMessage == null) return 0;
            using (var dc = new SMSAccess())
            {
                sendMessage.Status = (int)Status.Waitting;
                return dc.AddEntity<SendMessage>(sendMessage);
            }
        }

        public int AddSendMessages(SendMessage[] sendMessages)
        {
            if (sendMessages == null || sendMessages.Length == 0) return 0;
            using (var dc = new SMSAccess())
            {
                foreach (var sendMessage in sendMessages)
                {
                    sendMessage.Status = (int)Status.Waitting;
                }
                return dc.AddEntities<SendMessage>(sendMessages);
            }
        }

        public int UpdateSendMessage(SendMessage sendMessage)
        {
            using (var dc = new SMSAccess())
            {
                return dc.UpdateEntity<SendMessage>(sendMessage);
            }
        }

        public int UpdateSendMessages(SendMessage[] sendMessages)
        {
            using (var dc = new SMSAccess())
            {
                return dc.UpdateEntities<SendMessage>(sendMessages);
            }
        }

        public int DeleteSendMessage(string sendKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.DeleteEntity<SendMessage>(d => d.SendKeyid == sendKeyid);
            }
        }

        public int DeleteSendMessages(string[] sendKeyids)
        {
            using (var dc = new SMSAccess())
            {
                return dc.DeleteEntity<SendMessage>(d => sendKeyids.Contains(d.SendKeyid));
            }
        }

        #endregion

        #region ReceiveMessage

        public ReceiveMessage GetReceiveMessage(string receiveKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetSingleEntity<ReceiveMessage>(d => d.ReceiveKeyid == receiveKeyid);
            }
        }

        public ReceiveMessage[] GetReplyMessage(string sendKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<ReceiveMessage>(d => d.SendKeyid == sendKeyid).ToArray();
            }
        }

        public ReceiveMessage[] GetReplyReceiveMessage(string receiveNumber, string replyCode)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<ReceiveMessage>(d => d.ReceiveNumber == receiveNumber && d.ReplyCode == replyCode).ToArray();
            }
        }

        public SearchResult<ReceiveMessage> SearchReceiveMessage(SearchCondition condition)
        {
            using (var dc = new SMSAccess())
            {
                return dc.Search<ReceiveMessage>(condition);
            }
        }

        public int AddReceiveMessage(ReceiveMessage receiveMessage)
        {
            using (var dc = new SMSAccess())
            {
                return dc.AddEntity<ReceiveMessage>(receiveMessage);
            }
        }

        public int AddReceiveMessages(ReceiveMessage[] receiveMessages)
        {
            using (var dc = new SMSAccess())
            {
                return dc.AddEntities<ReceiveMessage>(receiveMessages);
            }
        }

        public int UpdateReceiveMessage(ReceiveMessage receiveMessage)
        {
            using (var dc = new SMSAccess())
            {
                return dc.UpdateEntity<ReceiveMessage>(receiveMessage);
            }
        }

        public int UpdateReceiveMessages(ReceiveMessage[] receiveMessages)
        {
            using (var dc = new SMSAccess())
            {
                return dc.UpdateEntities<ReceiveMessage>(receiveMessages);
            }
        }

        public int DeleteReceiveMessage(string receiveKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.DeleteEntity<ReceiveMessage>(d => d.ReceiveKeyid == receiveKeyid);
            }
        }

        public int DeleteReceiveMessages(string[] receiveKeyids)
        {
            using (var dc = new SMSAccess())
            {
                return dc.DeleteEntity<ReceiveMessage>(d => receiveKeyids.Contains(d.ReceiveKeyid));
            }
        }

        #endregion

        #region SMSMessage

        public SMSMessage[] GetSendSMSMessage(string sendKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<SMSMessage>(d => d.SendKeyid == sendKeyid).ToArray();
            }
        }

        public SMSMessage GetReceiveSMSMessage(string receiveKeyid)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetSingleEntity<SMSMessage>(d => d.ReceiveKeyid == receiveKeyid);
            }
        }

        public SMSMessage[] GetEventTagSMSMessage(string eventTag)
        {
            using (var dc = new SMSAccess())
            {
                return dc.GetEntityList<SMSMessage>(d => d.EventTag == eventTag).ToArray();
            }
        }

        public SearchResult<SMSMessage> SearchSMSMessage(SearchCondition condition)
        {
            using (var dc = new SMSAccess())
            {
                return dc.Search<SMSMessage>(condition);
            }
        }

        #endregion

        #endregion
    }
}